using System;
using System.ComponentModel.Design;
using System.IO;
using System.Windows.Forms;
using OpenComposite.EII.Designer;

namespace OpenComposite.EII
{
	public class RepositorySurfaceManager : DesignSurfaceManager
	{
		#region Initialization
		public RepositorySurfaceManager()
			: base()
		{
			//this.AddService(typeof(INameCreationService), new NameCreationService());
			RepositoryService repservice = new RepositoryService(this);
			this.AddService(typeof(RepositorySurfaceManager), this);
			this.AddService(typeof(RepositoryService), repservice);
			this.AddService(typeof(Services.IRepositoryChangeService), repservice);
			this.AddService(typeof(Services.IRepositorySelectionService), new Services.RepositorySelectionService(this));

			this.ActiveDesignSurfaceChanged +=
				new ActiveDesignSurfaceChangedEventHandler(RepositorySurfaceManager_ActiveDesignSurfaceChanged);
		}
		#endregion

		#region Public Members

		#region Methods
        /// <summary>
        /// Gets a new HostSurface and loads it with the appropriate type of
        /// root component. Uses the appropriate Loader to load the HostSurface.
        /// </summary>
		public RepositoryContent GetNewHost(Type rootComponentType, LoaderType loaderType)
		{
			if ( loaderType == LoaderType.None )
				return getNewHost(rootComponentType);

			RepositorySurface surface = (RepositorySurface)this.CreateDesignSurface(this.ServiceContainer);
			IDesignerHost host = (IDesignerHost)surface.GetService(typeof(IDesignerHost));

			switch (loaderType)
			{
				case LoaderType.BasicDesignerLoader :
					//BasicHostLoader basicHostLoader = new BasicHostLoader(rootComponentType);
					//surface.BeginLoad(basicHostLoader);
					//surface.Loader = basicHostLoader;
					break;

				case LoaderType.CodeDomDesignerLoader :
					//CodeDomHostLoader codeDomHostLoader = new CodeDomHostLoader();
					//surface.BeginLoad(codeDomHostLoader);
					//surface.Loader = codeDomHostLoader;
					break;

				default:
					throw new Exception("Loader is not defined: " + loaderType.ToString());
			}

			surface.Initialize(null);
			return new RepositoryContent(surface);
		}
        /// <summary>
        /// Opens an Xml file and loads it up using BasicHostLoader (inherits from
        /// BasicDesignerLoader)
        /// </summary>
		public RepositoryContent GetNewHost(string fileName)
		{
			if (fileName == null || !File.Exists(fileName))
				MessageBox.Show("FileName is incorrect: " + fileName);

			LoaderType loaderType = LoaderType.None;

			if (fileName.EndsWith("xml"))
				loaderType = LoaderType.BasicDesignerLoader;

			if ( loaderType == LoaderType.None || loaderType == LoaderType.CodeDomDesignerLoader )
            {
                throw new Exception("File cannot be opened. Please check the type or extension of the file. Supported format is Xml");
            }

			RepositorySurface surface = (RepositorySurface)this.CreateDesignSurface(this.ServiceContainer);
			IDesignerHost host = (IDesignerHost)surface.GetService(typeof(IDesignerHost));

			//BasicHostLoader basicHostLoader = new BasicHostLoader(fileName);
			//surface.BeginLoad(basicHostLoader);
			//surface.Loader = basicHostLoader;
			//surface.Initialize();
			return new RepositoryContent(surface);
		}

		public RepositorySurface CreateControllerSurface(IController controller)
		{
			RepositorySurface surface = (RepositorySurface)this.CreateDesignSurface(this.ServiceContainer);
			surface.Initialize(controller);
			return surface;
		}

		public void AddService(Type type, object serviceInstance)
		{
			if ( this.ServiceContainer.GetService(type) != null )
				this.ServiceContainer.RemoveService(type);

			this.ServiceContainer.AddService(type, serviceInstance);
		}
		#endregion

		#endregion

		#region Protected Members

		#region Methods
		// override
		protected override DesignSurface CreateDesignSurfaceCore(IServiceProvider parentProvider)
		{
			return new RepositorySurface(parentProvider);
		}
		#endregion

		#endregion

		#region Private Members

		#region Methods
		/// <summary>
        /// Gets a new HostSurface and loads it with the appropriate type of
        /// root component. 
        /// </summary>
        private RepositoryContent getNewHost(Type rootComponentType)
		{
			RepositorySurface hostSurface = (RepositorySurface)this.CreateDesignSurface(this.ServiceContainer);

			//if (rootComponentType == typeof(Form))
			//    hostSurface.BeginLoad(typeof(Form));
			//else if (rootComponentType == typeof(UserControl))
			//    hostSurface.BeginLoad(typeof(UserControl));
			//else if (rootComponentType == typeof(Component))
			//    hostSurface.BeginLoad(typeof(Component));
			//else if (rootComponentType == typeof(MyTopLevelComponent))
			//    hostSurface.BeginLoad(typeof(MyTopLevelComponent));
			//else
			//    throw new Exception("Undefined Host Type: " + rootComponentType.ToString());

			hostSurface.Initialize(null);
			this.ActiveDesignSurface = hostSurface;
			return new RepositoryContent(hostSurface);
		}
		#endregion

		#region Event Handlers
        /// <summary>
        /// Uses the OutputWindow service and writes out to it.
        /// </summary>
		void RepositorySurfaceManager_ActiveDesignSurfaceChanged(object sender, ActiveDesignSurfaceChangedEventArgs e)
		{
			//ToolWindows.OutputWindow o = this.GetService(typeof(ToolWindows.OutputWindow)) as ToolWindows.OutputWindow;
			//o.RichTextBox.Text += "New host added.\n";
		}
		#endregion

		#endregion
	}

	#region Enum: LoaderType
	public enum LoaderType
	{
		None = 0,
		BasicDesignerLoader = 1,
		CodeDomDesignerLoader = 2
	}
	#endregion

}
